package com.tiancikeji.zaoke.app.biz.impl;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.commons.lang.StringUtils;

import com.tiancikeji.zaoke.app.biz.FoodBiz;
import com.tiancikeji.zaoke.app.comparator.FoodComparator;
import com.tiancikeji.zaoke.app.comparator.FoodTagComparator;
import com.tiancikeji.zaoke.app.model.food.Food;
import com.tiancikeji.zaoke.app.model.food.FoodImage;
import com.tiancikeji.zaoke.app.model.food.FoodNutrition;
import com.tiancikeji.zaoke.app.model.food.FoodPrice;
import com.tiancikeji.zaoke.app.model.food.FoodPromotion;
import com.tiancikeji.zaoke.app.model.food.FoodTag;
import com.tiancikeji.zaoke.app.service.food.FoodImageService;
import com.tiancikeji.zaoke.app.service.food.FoodNutritionService;
import com.tiancikeji.zaoke.app.service.food.FoodPromotionService;
import com.tiancikeji.zaoke.app.service.food.FoodService;
import com.tiancikeji.zaoke.app.service.food.FoodTagService;

public class FoodBizImpl implements FoodBiz {
	
	public static final int DEFAULT_COMBO_MARGIN = 0;

	public static final int DEFAULT_TAGS_CNT = 3;

	public static final String DEFAULT_URL_PREFIX = "http://zaocan.tiancikeji.com/img/";
	
	public static final String DEFAULT_FOOD_TYPE = "1";
	
	private String foodType = DEFAULT_FOOD_TYPE;
	
	private String urlPrefix = DEFAULT_URL_PREFIX;
	
	private int comboMargin = DEFAULT_COMBO_MARGIN;
	
	private int tagsCnt = DEFAULT_TAGS_CNT;
	
	private FoodService foodService;
	
	private FoodImageService foodImageService;
	
	private FoodPromotionService foodPromotionService;
	
	private FoodTagService foodTagService;
	
	private FoodNutritionService foodNutritionService;

	public FoodPrice getFoodPrice(Food food1, Food food2) {
		FoodPrice price = new FoodPrice();
		
		if(food1 != null && food2 != null && food1.getType() == food2.getType())
			return price;
		
		if(food1 != null || food2 != null){
			// single price
			double salePrice = 0;
			if(food1 != null)
				salePrice += food1.getSalePrice();
			if(food2 != null)
				salePrice += food2.getSalePrice();
			price.setSalePrice(salePrice);
			
			// combo price
			if(food1 != null && food2 != null)
				price.setComboPrice(price.getSalePrice() - _getComboMargin());
			
			// promotion price - food1
			if(food1 != null && food1.getPromotion() != null){
				if(food2 == null && food1.getPromotion().getSingleMargin() > 0)
					price.setPromotionPrice(price.getSalePrice() - food1.getPromotion().getSingleMargin());
				
				if(food2 != null && food1.getPromotion().getComboMargin() > 0)
					price.setPromotionPrice(price.getComboPrice() - food1.getPromotion().getComboMargin());
			} 

			// promotion price - food2
			if(food2 != null && food2.getPromotion() != null){
				if(food1 == null && food2.getPromotion().getSingleMargin() > 0)
					price.setPromotionPrice(price.getSalePrice() - food2.getPromotion().getSingleMargin());
				
				if(food1 != null && food2.getPromotion().getComboMargin() > 0)
					price.setPromotionPrice(price.getComboPrice() - food2.getPromotion().getComboMargin());
				
			}
		}
		
		return price;
	}

	private int _getComboMargin() {
		if(comboMargin > 0)
			return comboMargin;
		else
			return DEFAULT_COMBO_MARGIN;
	}

	public Food getFoodInfo(long foodId, int type) {
		if(foodId > 0){
			Food food = foodService.getFoodById(foodId);
			
			if(food != null && food.getId() == foodId){
				FoodImage image = foodImageService.getImageByFoodId(foodId, type);
				Set<FoodTag> tags = foodTagService.getTagByFoodId(foodId);
				FoodPromotion promotion = foodPromotionService.getTodayPromotionByFoodId(foodId);
				Set<FoodNutrition> nutritions = foodNutritionService.getNutritionByFoodId(foodId);
				
				if(image != null)
					setFoodImage(food, image);
				if(tags != null && tags.size() > 0)
					setFoodTags(food, tags);
				if(promotion != null)
					setFoodPromotion(food, promotion);
				if(nutritions != null && nutritions.size() > 0)
					setFoodNutritions(food, nutritions);
				
				return food;
			}
		}
		
		return null;
	}

	public Map<String, List<Food>> getFoodList(int type) {
		Map<String, List<Food>> result = new HashMap<String, List<Food>>();
		
		Set<Food> foods = foodService.getAllActiveFoods();
		
		if(foods != null && foods.size() > 0){
			Set<Long> ids = new HashSet<Long>();
			
			for(Food food : foods)
				ids.add(food.getId());
			
			Map<Long, FoodImage> images = foodImageService.getImageByFoodIds(ids, type);
			Map<Long, Set<FoodTag>> tags = foodTagService.getTagByFoodIds(ids);
			Map<Long, FoodPromotion> promotions = foodPromotionService.getTodayPromotionByFoodIds(ids);
			
			for(Food food : foods){
				if(images != null && images.containsKey(food.getId()))
					setFoodImage(food, images.get(food.getId()));

				if(promotions != null && promotions.containsKey(food.getId()))
					setFoodPromotion(food, promotions.get(food.getId()));

				if(tags != null && tags.containsKey(food.getId()))
					setFoodTags(food, tags.get(food.getId()));
				
				String key = new Integer(food.getType()).toString();
				List<Food> foods2 = result.get(key);
				if(foods2 == null){
					foods2 = new ArrayList<Food>();
					result.put(key, foods2);
				}
				foods2.add(food);
			}
			
			// sort
			if(result != null && result.size() > 0)
				for(String key : result.keySet())
					Collections.sort(result.get(key), new FoodComparator());
		}
		
		return result;
	}

	private void setFoodNutritions(Food food, Set<FoodNutrition> nutritions) {
		if(nutritions != null && nutritions.size() > 0){
			Set<FoodNutrition> tmp = new HashSet<FoodNutrition>();
			
			for(FoodNutrition nutrition : nutritions)
				if(StringUtils.isNotBlank(nutrition.getValue()) && nutrition.getNutrition() != null && StringUtils.isNotBlank(nutrition.getNutrition().getName()))
					tmp.add(nutrition);
			
			food.setNutritions(tmp);
		}
	}

	private void setFoodTags(Food food, Set<FoodTag> tags) {
		if(tags != null && tags.size() > 0){
			List<FoodTag> tag = new ArrayList<FoodTag>(); 
			
			for(FoodTag tmp : tags)
				if(StringUtils.isNotBlank(tmp.getTag()))
					tag.add(tmp);
			
			Collections.sort(tag, new FoodTagComparator());
			
			if(tag.size() > 0){
				// FIXME first 3 currently?
				if(tag.size() > DEFAULT_TAGS_CNT)
					food.setTags(tag.subList(0, DEFAULT_TAGS_CNT));
				else
					food.setTags(tag);
			}
		}
	}

	private void setFoodPromotion(Food food, FoodPromotion promotion) {
		if(promotion != null){
			if(promotion.getSingleMargin() > 0){
				double tmp = food.getSalePrice() - promotion.getSingleMargin();
				if(tmp < 0)
					tmp = 0;
				food.setSalePrice(tmp);
				promotion.setSingleMargin(0);
				food.setPromotion(promotion);
			}
			if(promotion.getComboMargin() > 0)
				food.setPromotion(promotion);
		}
	}

	// FIXME url prefix
	private void setFoodImage(Food food, FoodImage image) {
		if(image != null && StringUtils.isNotBlank(image.getUrl())){
			if(!StringUtils.startsWith(image.getUrl(), getImageUrlPrefix()))
					image.setUrl(getImageUrlPrefix() + image.getUrl());
			food.setImage(image);
		}
	}
	
	private String getImageUrlPrefix() {
		if(StringUtils.isNotBlank(urlPrefix))
			return urlPrefix;
		else
			return DEFAULT_URL_PREFIX;
	}

	public String getDefaultFoodType() {
		if(StringUtils.isNotBlank(foodType))
			return foodType;
		else
			return DEFAULT_FOOD_TYPE;
	}

	public String getFoodType() {
		return foodType;
	}

	public void setFoodType(String foodType) {
		this.foodType = foodType;
	}

	public FoodService getFoodService() {
		return foodService;
	}

	public void setFoodService(FoodService foodService) {
		this.foodService = foodService;
	}

	public FoodImageService getFoodImageService() {
		return foodImageService;
	}

	public void setFoodImageService(FoodImageService foodImageService) {
		this.foodImageService = foodImageService;
	}

	public FoodNutritionService getFoodNutritionService() {
		return foodNutritionService;
	}

	public void setFoodNutritionService(FoodNutritionService foodNutritionService) {
		this.foodNutritionService = foodNutritionService;
	}

	public FoodPromotionService getFoodPromotionService() {
		return foodPromotionService;
	}

	public void setFoodPromotionService(FoodPromotionService foodPromotionService) {
		this.foodPromotionService = foodPromotionService;
	}

	public FoodTagService getFoodTagService() {
		return foodTagService;
	}

	public void setFoodTagService(FoodTagService foodTagService) {
		this.foodTagService = foodTagService;
	}

	public String getUrlPrefix() {
		return urlPrefix;
	}

	public void setUrlPrefix(String urlPrefix) {
		this.urlPrefix = urlPrefix;
	}

	public int getTagsCnt() {
		return tagsCnt;
	}

	public void setTagsCnt(int tagsCnt) {
		this.tagsCnt = tagsCnt;
	}

	public int getComboMargin() {
		return comboMargin;
	}

	public void setComboMargin(int comboMargin) {
		this.comboMargin = comboMargin;
	}

}
